﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PaceR.Core.Extensions
{
    public static class CollectionExtensions
    {
		public static bool TryReplaceOne<T>(this IList<T> list, T replacement, Func<T, bool> search)
		{
			if (list != null && search != null && !list.IsReadOnly)
			{
				var found = list.FirstOrDefault(search);
				if (found != null)
				{
					int i = list.IndexOf(found);
					list[i] = replacement;
					return true;
				} 
			}

			return false;
		}

		public static bool TryReplaceOrAddOne<T>(this IList<T> list, T replacement, Func<T, bool> search)
		{
			if (list != null && search != null && !list.IsReadOnly)
			{
				if (!list.TryReplaceOne(replacement, search))
				{
					if (!(list is IList) || !((IList)list).IsFixedSize)
					{
						list.Add(replacement);
						return true;
					}
				}
			}

			return false;
		}

		public static IEnumerable<T> CopyAndReplaceOne<T>(this IEnumerable<T> list, T replacement, Func<T, bool> search)
		{
			IEnumerable<T> result = null;

			TryReplaceOne(list, replacement, search, out result);

			return result;
		}

		public static IEnumerable<T> CopyAndReplaceOrAddOne<T>(this IEnumerable<T> list, T replacement, Func<T, bool> search)
		{
			IEnumerable<T> result = null;

			if (list != null)
			{
				if (!TryReplaceOne(list, replacement, search, out result))
				{
					result = list.ToList();
					((List<T>)result).Add(replacement);
				}
			}

			return result;
		}
		
        public static bool TryRemoveWhere<T>(this ICollection<T> list, Func<T, bool> predicate)
        {
            if (list != null && predicate != null && (!(list is IList) || !((IList)list).IsFixedSize))
			{
				var found = list.Where(predicate).ToArray();
				foreach (var item in found)
				{
					list.Remove(item);
				}
				return true;
			}

			return false;
        }

		public static bool TryReplaceOne<T>(IEnumerable<T> list, T replacement, Func<T, bool> search, out IEnumerable<T> transformedList)
		{
			bool found = false;

			if (list != null)
			{
				transformedList = list.Select(l =>
				{
					if (search(l) && !found)
					{
						found = true;
						return replacement;
					}
					return l;
				});
			}
			else transformedList = null;

			return found;
		}

		public static bool TryRemoveWhere<T>(this IEnumerable<T> list, Func<T, bool> predicate, out IEnumerable<T> transformedList)
		{
			if (list != null && predicate != null)
			{
				transformedList = list.Where(l => !predicate(l));
				return true;
			}
			else
			{
				transformedList = null;
				return false;
			}
		}
    }
}
